--------------------------------------------------------------------------------
-- This package is a thick Ada binding to the GNU Multiple Precision Library.
-- See <http://gmplib.org/>.
--
-- Copyright (C) 2009 Vincent DIEMUNSCH.
-- GNU General Public License.
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU General Public License as published by the Free Software
-- Foundation, either version 3 of the License, or (at your option) any later
-- version.
--
-- This file is distributed in the hope that it will be useful, but WITHOUT ANY
-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License along with
-- this program.  If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------------
--
-- This package declares a new private type : Unbounded_Fraction, that is an
-- abstraction of rational (common fraction) of arbitrary size.

with Ada.Finalization;
with Fractions;          use Fractions;
with GMP.Integers;       use GMP.Integers;

package GMP.Rationals is

   type Unbounded_Fraction is private;
   -- Private type so that all the following functions are
   -- NOT primitive operations.

   function "/" (Left, Right : Unbounded_Integer) return Unbounded_Fraction;
   -- constructor, the Unbounded Fraction will be in canonical form.

   function Numerator   (F : Unbounded_Fraction) return Unbounded_Integer;
   function Denominator (F : Unbounded_Fraction) return Unbounded_Integer;

   function Image   (Object : Unbounded_Fraction;
                     Base   : Base_Range := 10 ) return String;
   -- This function use the image function of Unbounded_Integer to build a
   -- string composed of two (decimal or base) literals separated by a " / ".

   ----------------------------
   -- "Standard" description --
   ----------------------------

   -- (Mimics Standard package)
   -- The operators for the type are as follows:

   function "="  (Left, Right : Unbounded_Fraction) return Boolean;
   function "<"  (Left, Right : Unbounded_Fraction) return Boolean;
   function "<=" (Left, Right : Unbounded_Fraction) return Boolean;
   function ">"  (Left, Right : Unbounded_Fraction) return Boolean;
   function ">=" (Left, Right : Unbounded_Fraction) return Boolean;

   function "+"   (Right : Unbounded_Fraction) return Unbounded_Fraction;
   function "-"   (Right : Unbounded_Fraction) return Unbounded_Fraction;
   function "abs" (Right : Unbounded_Fraction) return Unbounded_Fraction;

   function "+"   (Left, Right : Unbounded_Fraction) return Unbounded_Fraction;
   function "-"   (Left, Right : Unbounded_Fraction) return Unbounded_Fraction;
   function "*"   (Left, Right : Unbounded_Fraction) return Unbounded_Fraction;
   function "/"   (Left, Right : Unbounded_Fraction) return Unbounded_Fraction;

   function inv   (Right : Unbounded_Fraction) return Unbounded_Fraction;

   function "**"  (Left : Unbounded_Fraction; Right : Integer'Base) return Unbounded_Fraction;

   -----------------------------
   -- with Standard Fractions --
   -----------------------------
    -- The given Fraction is supposed to be already canonicalized.

   function To_Unbounded_Fraction (F : Fraction) return Unbounded_Fraction;

   function "+" (Left : Unbounded_Fraction; Right : Fraction) return Unbounded_Fraction;
   function "-" (Left : Unbounded_Fraction; Right : Fraction) return Unbounded_Fraction;
   function "-" (Left : Fraction; Right : Unbounded_Fraction) return Unbounded_Fraction;
   function "*" (Left : Unbounded_Fraction; Right : Fraction) return Unbounded_Fraction;
   function "/" (Left : Unbounded_Fraction; Right : Fraction) return Unbounded_Fraction;
   function "/" (Left : Fraction; Right : Unbounded_Fraction) return Unbounded_Fraction;


private

   type Unbounded_Fraction is new Ada.Finalization.Controlled with record
      Value : mpq_t;
   end record;

   overriding procedure Initialize (Object: in out Unbounded_Fraction);
   overriding procedure Adjust     (Object: in out Unbounded_Fraction);
   overriding procedure Finalize   (Object: in out Unbounded_Fraction);

end GMP.Rationals;
